home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 March / macformat-022.iso / Shareware City / Developers / src / out-of-phase-102-c / OutOfPhase 1.02 Source / OutOfPhase Folder / ASTAssignment.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-23  |  10.5 KB  |  305 lines  |  [TEXT/KAHL]

  1. /* ASTAssignment.c */
  2. /*****************************************************************************/
  3. /*                                                                           */
  4. /*    Out Of Phase:  Digital Music Synthesis on General Purpose Computers    */
  5. /*    Copyright (C) 1994  Thomas R. Lawrence                                 */
  6. /*                                                                           */
  7. /*    This program is free software; you can redistribute it and/or modify   */
  8. /*    it under the terms of the GNU General Public License as published by   */
  9. /*    the Free Software Foundation; either version 2 of the License, or      */
  10. /*    (at your option) any later version.                                    */
  11. /*                                                                           */
  12. /*    This program is distributed in the hope that it will be useful,        */
  13. /*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
  14. /*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
  15. /*    GNU General Public License for more details.                           */
  16. /*                                                                           */
  17. /*    You should have received a copy of the GNU General Public License      */
  18. /*    along with this program; if not, write to the Free Software            */
  19. /*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
  20. /*                                                                           */
  21. /*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
  22. /*                                                                           */
  23. /*****************************************************************************/
  24.  
  25. #include "MiscInfo.h"
  26. #include "Audit.h"
  27. #include "Debug.h"
  28. #include "Definitions.h"
  29.  
  30. #include "ASTAssignment.h"
  31. #include "ASTExpression.h"
  32. #include "TrashTracker.h"
  33. #include "Memory.h"
  34. #include "PromotableTypeCheck.h"
  35. #include "ASTOperand.h"
  36. #include "SymbolTableEntry.h"
  37. #include "ASTBinaryOperator.h"
  38.  
  39.  
  40. struct ASTAssignRec
  41.     {
  42.         ASTExpressionRec*            LValueGenerator;
  43.         ASTExpressionRec*            ObjectValue;
  44.         long                                    LineNumber;
  45.     };
  46.  
  47.  
  48. /* create a new assignment node */
  49. ASTAssignRec*                NewAssignment(struct ASTExpressionRec* LeftValue,
  50.                                             struct ASTExpressionRec* RightValue,
  51.                                             struct TrashTrackRec* TrashTracker, long LineNumber)
  52.     {
  53.         ASTAssignRec*        Assignment;
  54.  
  55.         CheckPtrExistence(LeftValue);
  56.         CheckPtrExistence(RightValue);
  57.         CheckPtrExistence(TrashTracker);
  58.         Assignment = (ASTAssignRec*)AllocTrackedBlock(sizeof(ASTAssignRec),TrashTracker);
  59.         if (Assignment == NIL)
  60.             {
  61.                 return NIL;
  62.             }
  63.         SetTag(Assignment,"ASTAssignRec");
  64.  
  65.         Assignment->LineNumber = LineNumber;
  66.         Assignment->LValueGenerator = LeftValue;
  67.         Assignment->ObjectValue = RightValue;
  68.  
  69.         return Assignment;
  70.     }
  71.  
  72.  
  73. /* type check the assignment node.  this returns eCompileNoError if */
  74. /* everything is ok, and the appropriate type in *ResultingDataType. */
  75. CompileErrors                TypeCheckAssignment(DataTypes* ResultingDataType,
  76.                                             ASTAssignRec* Assignment, long* ErrorLineNumber,
  77.                                             struct TrashTrackRec* TrashTracker)
  78.     {
  79.         CompileErrors            Error;
  80.         DataTypes                    RValueType;
  81.         DataTypes                    LValueType;
  82.  
  83.         CheckPtrExistence(Assignment);
  84.         CheckPtrExistence(TrashTracker);
  85.  
  86.         Error = TypeCheckExpression(&RValueType,Assignment->ObjectValue,ErrorLineNumber,
  87.             TrashTracker);
  88.         if (Error != eCompileNoError)
  89.             {
  90.                 return Error;
  91.             }
  92.  
  93.         Error = TypeCheckExpression(&LValueType,Assignment->LValueGenerator,ErrorLineNumber,
  94.             TrashTracker);
  95.         if (Error != eCompileNoError)
  96.             {
  97.                 return Error;
  98.             }
  99.  
  100.         if (!CanRightBeMadeToMatchLeft(LValueType,RValueType))
  101.             {
  102.                 *ErrorLineNumber = Assignment->LineNumber;
  103.                 return eCompileTypeMismatch;
  104.             }
  105.  
  106.         if (MustRightBePromotedToLeft(LValueType,RValueType))
  107.             {
  108.                 ASTExpressionRec*        ReplacementRValue;
  109.  
  110.                 /* insert promotion operator above right hand side */
  111.                 ReplacementRValue = PromoteTheExpression(RValueType,LValueType,
  112.                     Assignment->ObjectValue,Assignment->LineNumber,TrashTracker);
  113.                 if (ReplacementRValue == NIL)
  114.                     {
  115.                         *ErrorLineNumber = Assignment->LineNumber;
  116.                         return eCompileOutOfMemory;
  117.                     }
  118.                 Assignment->ObjectValue = ReplacementRValue;
  119.                 /* sanity check */
  120.                 Error = TypeCheckExpression(&RValueType,Assignment->ObjectValue,ErrorLineNumber,
  121.                     TrashTracker);
  122.                 ERROR((Error != eCompileNoError),PRERR(ForceAbort,
  123.                     "TypeCheckAssignment:  type promotion caused failure"));
  124.                 ERROR(RValueType != LValueType,PRERR(ForceAbort,
  125.                     "TypeCheckAssignment:  after type promotion, types are no longer the same"));
  126.             }
  127.  
  128.         /* make sure it's a valid lvalue */
  129.         if (!IsExpressionValidLValue(Assignment->LValueGenerator))
  130.             {
  131.                 *ErrorLineNumber = Assignment->LineNumber;
  132.                 return eCompileInvalidLValue;
  133.             }
  134.  
  135.         *ResultingDataType = LValueType;
  136.         return eCompileNoError;
  137.     }
  138.  
  139.  
  140. /* generate code for an assignment.  returns True if successful, or False if it fails. */
  141. MyBoolean                        CodeGenAssignment(struct PcodeRec* FuncCode,
  142.                                             long* StackDepthParam, ASTAssignRec* Assignment)
  143.     {
  144.         long                            StackDepth;
  145.  
  146.         CheckPtrExistence(FuncCode);
  147.         CheckPtrExistence(Assignment);
  148.         StackDepth = *StackDepthParam;
  149.  
  150.         /* find out what kind of assignment operation to perform */
  151.         /*  - for single variables:  it stores the value from top of stack into the */
  152.         /*    appropriate index, but does not pop the value. */
  153.         /*  - for array variables:  the array index is computed and pushed on the */
  154.         /*    stack.  then the array index is popped, and the element value is stored. */
  155.         /*    the element value is NOT popped. */
  156.         switch (WhatKindOfExpressionIsThis(Assignment->LValueGenerator))
  157.             {
  158.                 default:
  159.                     EXECUTE(PRERR(ForceAbort,"CodeGenAssignment:  bad lvalue expression type"));
  160.                     break;
  161.  
  162.                 case eExprOperand:
  163.                     {
  164.                         ASTOperandRec*        TheOperand;
  165.                         SymbolRec*                TheVariable;
  166.                         Pcodes                        TheAssignmentOpcode;
  167.  
  168.                         /* evaluate the value expression.  this leaves the result on the stack */
  169.                         if (!CodeGenExpression(FuncCode,&StackDepth,Assignment->ObjectValue))
  170.                             {
  171.                                 return False;
  172.                             }
  173.                         ERROR(StackDepth != *StackDepthParam + 1,PRERR(ForceAbort,
  174.                             "CodeGenAssignment:  CodeGenExpression made stack depth bad"));
  175.  
  176.                         /* get the variable being assigned to */
  177.                         TheOperand = GetOperandOutOfExpression(Assignment->LValueGenerator);
  178.                         TheVariable = GetSymbolFromOperand(TheOperand);
  179.  
  180.                         /* generate the assignment opcode word */
  181.                         switch (GetSymbolVariableDataType(TheVariable))
  182.                             {
  183.                                 default:
  184.                                     EXECUTE(PRERR(ForceAbort,
  185.                                         "CodeGenAssignment:  variable has unknown type"));
  186.                                     break;
  187.                                 case eBoolean:
  188.                                 case eInteger:
  189.                                 case eFixed:
  190.                                     TheAssignmentOpcode = epStoreIntegerOnStack;
  191.                                     break;
  192.                                 case eFloat:
  193.                                     TheAssignmentOpcode = epStoreFloatOnStack;
  194.                                     break;
  195.                                 case eDouble:
  196.                                     TheAssignmentOpcode = epStoreDoubleOnStack;
  197.                                     break;
  198.                                 case eArrayOfBoolean:
  199.                                 case eArrayOfInteger:
  200.                                 case eArrayOfFloat:
  201.                                 case eArrayOfDouble:
  202.                                 case eArrayOfFixed:
  203.                                     TheAssignmentOpcode = epStoreArrayOnStack;
  204.                                     break;
  205.                             }
  206.                         if (!AddPcodeInstruction(FuncCode,TheAssignmentOpcode,NIL))
  207.                             {
  208.                                 return False;
  209.                             }
  210.  
  211.                         /* generate the assignment operand (destination variable index) */
  212.                         /* stack offsets are negative. */
  213.                         if (!AddPcodeOperandInteger(FuncCode,
  214.                             GetSymbolVariableStackLocation(TheVariable) - StackDepth))
  215.                             {
  216.                             }
  217.                     }
  218.                     break;
  219.  
  220.                 case eExprBinaryOperator:
  221.                     {
  222.                         ASTBinaryOpRec*        TheBinaryOperator;
  223.                         ASTExpressionRec*    LeftOperand;
  224.                         ASTExpressionRec*    RightOperand;
  225.                         Pcodes                        TheAssignmentOpcode;
  226.  
  227.                         TheBinaryOperator = GetBinaryOperatorOutOfExpression(
  228.                             Assignment->LValueGenerator);
  229.                         LeftOperand = GetLeftOperandForBinaryOperator(TheBinaryOperator);
  230.                         RightOperand = GetRightOperandForBinaryOperator(TheBinaryOperator);
  231.                         /* the left operand is the array reference generator */
  232.                         /* the right operand is the array index generator. */
  233.  
  234.                         /* 1. evaluate the expression that's going to be assigned, leave on stack */
  235.                         /* 2. evaluate array reference, leaving it on the stack */
  236.                         /* 3. evaluate array subscript, leaving it on the stack */
  237.                         /* 4. do assignment which */
  238.                         /*     - pops subscript */
  239.                         /*     - stores into array thing */
  240.                         /*     - value is left on stack */
  241.  
  242.                         /* 1.  evaluate the value expression */
  243.                         if (!CodeGenExpression(FuncCode,&StackDepth,Assignment->ObjectValue))
  244.                             {
  245.                                 return False;
  246.                             }
  247.                         ERROR(StackDepth != *StackDepthParam + 1,PRERR(ForceAbort,
  248.                             "CodeGenAssignment:  eval array element new value messed up stack"));
  249.  
  250.                         /* 2.  evaluate array reference */
  251.                         if (!CodeGenExpression(FuncCode,&StackDepth,LeftOperand))
  252.                             {
  253.                                 return False;
  254.                             }
  255.                         ERROR(StackDepth != *StackDepthParam + 2,PRERR(ForceAbort,
  256.                             "CodeGenAssignment:  eval array reference messed up stack"));
  257.  
  258.                         /* 3.  evaluate array subscript */
  259.                         if (!CodeGenExpression(FuncCode,&StackDepth,RightOperand))
  260.                             {
  261.                                 return False;
  262.                             }
  263.                         ERROR(StackDepth != *StackDepthParam + 3,PRERR(ForceAbort,
  264.                             "CodeGenAssignment:  eval array subscript messed up stack"));
  265.  
  266.                         /* 4.  generate the opcode for storing into an array */
  267.                         switch (GetExpressionsResultantType(LeftOperand))
  268.                             {
  269.                                 default:
  270.                                     EXECUTE(PRERR(ForceAbort,
  271.                                         "CodeGenAssignment:  array assignment bad result type"));
  272.                                     break;
  273.                                 case eArrayOfBoolean:
  274.                                     TheAssignmentOpcode = epStoreBooleanIntoArray2;
  275.                                     break;
  276.                                 case eArrayOfInteger:
  277.                                     TheAssignmentOpcode = epStoreIntegerIntoArray2;
  278.                                     break;
  279.                                 case eArrayOfFloat:
  280.                                     TheAssignmentOpcode = epStoreFloatIntoArray2;
  281.                                     break;
  282.                                 case eArrayOfDouble:
  283.                                     TheAssignmentOpcode = epStoreDoubleIntoArray2;
  284.                                     break;
  285.                                 case eArrayOfFixed:
  286.                                     TheAssignmentOpcode = epStoreFixedIntoArray2;
  287.                                     break;
  288.                             }
  289.                         if (!AddPcodeInstruction(FuncCode,TheAssignmentOpcode,NIL))
  290.                             {
  291.                                 return False;
  292.                             }
  293.                         StackDepth -= 2; /* popping the array subscript */
  294.                         ERROR(StackDepth != *StackDepthParam + 1,PRERR(ForceAbort,
  295.                             "CodeGenAssignment:  eval store into array internal stack messing"));
  296.                     }
  297.                     break;
  298.             }
  299.         ERROR(StackDepth != *StackDepthParam + 1,PRERR(ForceAbort,
  300.             "CodeGenAssignment:  after assignment, stack state is bad"));
  301.  
  302.         *StackDepthParam = StackDepth;
  303.         return True;
  304.     }
  305.